package cz.data.domain.market.utils;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.JdbcNamedParameter;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.parser.SimpleNode;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SelectItemVisitorAdapter;
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;
import net.sf.jsqlparser.util.validation.validator.ItemsListValidator;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SingleStatementVisitorAdapter extends StatementVisitorAdapter {
    // 返回字段
    private final List<Map<String, String>> cols;
    // 查询入参字段
    private final List<String> vars;
    private final String tableName;

    public SingleStatementVisitorAdapter(List<Map<String, String>> cols, List<String> vars, String tableName) {
        this.cols = cols;
        this.vars = vars;
        this.tableName = tableName;
    }

    @Override
    public void visit(Select select) {
        select.getSelectBody().accept(new SelectVisitorAdapter() {
            @Override
            public void visit(PlainSelect plainSelect) {
                plainSelect.getSelectItems().forEach(selectItem -> selectItem.accept(new SelectItemVisitorAdapter() {
                    @Override
                    public void visit(AllColumns columns) {
                        Map<String, String> map = new HashMap<>();
                        map.put("tableName", tableName);
                        map.put("columnName", columns.getASTNode().jjtGetFirstToken().image);
                        cols.add(map);
                    }

                    @Override
                    public void visit(SelectExpressionItem item) {
                        Map<String, String> map = new HashMap<>();
                        String columnName;
                        SimpleNode node = item.getExpression().getASTNode();
                        Object value = node.jjtGetValue();
                        if (value instanceof Column) {
                            Column column = (Column) value;
                            columnName = column.getColumnName();
                            if (item.getAlias() != null) {
                                map.put("columnAliasName", item.getAlias().getName());
                            }
                        } else if (value instanceof Function) {
                            columnName = value.toString();
                        } else {
                            // 增加对select 'aaa' from table; 的支持
                            columnName = String.valueOf(value);
                            columnName = columnName.replace("'", "");
                            columnName = columnName.replace("\"", "");
                            columnName = columnName.replace("`", "");
                        }
                        columnName = columnName.replace("'", "");
                        columnName = columnName.replace("\"", "");
                        columnName = columnName.replace("`", "");
                        map.put("tableName", tableName);
                        map.put("columnName", columnName);
                        cols.add(map);
                    }
                }));
                Expression where = plainSelect.getWhere();
                if (where != null) {
                    where.accept(new ExpressionVisitorAdapter() {

                        @Override
                        public void visit(EqualsTo expr) {
                            super.visit(expr);
                        }

                        @Override
                        public void visit(JdbcNamedParameter jdbcNamedParameter) {
                            vars.add(jdbcNamedParameter.getName());
                        }
                    });
                }

            }
        });
    }

    @Override
    public void visit(Insert insert) {
        insert.getItemsList().accept(new ItemsListValidator() {
            @Override
            public void visit(ExpressionList expressionList) {
                expressionList.accept(new ExpressionVisitorAdapter() {
                    @Override
                    public void visit(JdbcNamedParameter parameter) {
                        vars.add(parameter.getName());
                    }
                });
            }
        });
    }

    @Override
    public void visit(Update update) {
        for (UpdateSet updateSet : update.getUpdateSets()) {
            for (Column column : updateSet.getColumns()) {
                vars.add(column.getColumnName());
            }
        }
        update.getWhere().accept(new ExpressionVisitorAdapter() {
            @Override
            public void visit(EqualsTo expr) {
                super.visit(expr);
            }

            @Override
            public void visit(JdbcNamedParameter jdbcNamedParameter) {
                vars.add(jdbcNamedParameter.getName());
            }
        });
    }

    @Override
    public void visit(Delete delete) {
        delete.getWhere().accept(new ExpressionVisitorAdapter() {
            @Override
            public void visit(EqualsTo expr) {
                super.visit(expr);
            }

            @Override
            public void visit(JdbcNamedParameter jdbcNamedParameter) {
                vars.add(jdbcNamedParameter.getName());
            }
        });
    }
}
